#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   BOOT_SecurityAccess_0x27_test.py
@Time    :   2025/04/08 13:31:28
@Author  :   YangLiang 
@Version :   1.0
@Contact :   yangl@genvict.com
@License :   (C)Copyright 2022-2025
@Desc    :   None
'''

# here put the import lib
from numpy import byte, bytes_, int16
from pytest_assume.plugin import assume
 
import pytest
import logging
import time
import requests
from sympy import I
# from sympy import assuming
from commDriver.TS_CAN import *
import allure
import sys
from collections.abc import Iterable

from sqlalchemy import false
sys.dont_write_bytecode = True
from aes_cmac import AESCMAC

SecurityAccess_Seed_NRC13 = [
    ("27", "7F 27 13"),
    ("27 11 15", "7F 27 13"),
    ("27 11 FF", "7F 27 13"),
    ("27 11 11 33 22", "7F 27 13"),
]

SecurityAccess_Seed_NRC12 = [
    ("27 03 11", "7F 27 12"),
    ("27 03", "7F 27 12"),
    ("27 05", "7F 27 12"),
    ("27 07", "7F 27 12"),
    ("27 09", "7F 27 12"),
    ("27 0B", "7F 27 12"),
    ("27 0D", "7F 27 12"),
    ("27 FF", "7F 27 12"),

]

SecurityAccess_Key_NRC13 = [
    ("27", "7F 27 13"),
    ("27 12", "7F 27 13"),
    ("27 12 FF", "7F 27 13"),
    ("27 12 11 33 22", "7F 27 13"),
    ("27 12" + "11" * 17 , "7F 27 13"),
    ("27 12" + "11" * 15 , "7F 27 13"),
]

SecurityAccess_Key_NRC12 = [
    ("27 03", "7F 27 12"),
    ("27 06", "7F 27 12"),
    ("27 08", "7F 27 12")
]

# 功能寻址请求
SecurityAccess_Noresponse = [
    ("27 01", ""),       
    ("27 11", ""),      
    ("27 02", ""), 
    ("27 12", ""),
    ("27 04", ""),
    ("27", ""),
    ("27 02 11 22 33", ""),
    ("27 01 11 22 33", ""),
    ("27 12 11 22 33", ""),
    ("27 11 11 22 33", ""),
    ("27 07 11 22 33", ""),
    ("27 81 11 22 33", ""),     
]

level2_key = [0xB7,0xD7,0xD3,0x1C,0x54,0xA1,0xC6,0x25,0x71,0x7A,0x70,0x84,0xE6,0x39,0x86,0x88]

class Test_BOOT_SecurityAccess_Phy(object):

    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-安全访问请求种子正响应')
    @allure.description('测试物理寻址编程会话下请求种子的正响应')
    def test_SecurityAccess_Seed_Programming_Phy(self, action, Driver):
        iStep = 1
        time.sleep(0.1)
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
        with assume: 
            assert size == 18
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 0, iStep, False)
        with assume: 
            assert size == 18
        iStep = Driver['CAN'].unlock(Driver, iStep, 2)

    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-安全访问请求种子NRC35 36 37错误码')
    @allure.description('测试物理寻址编程会话下请求种子的NRC35 36 37错误码')
    def test_SecurityAccess_Seed_NRC35_36_37_Programming_Phy(self, action, Driver):
        iStep = 1
        # 构造密钥请求报文：服务ID(27) + 子功能(02) + 16字节测试密钥(22)
        reqKey = '27 12' + ' 22' * 16  # 共34字节(18个双字符)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '7F 27 7F', 1, iStep, False)
        # 第一次
        logging.info("first answer NRC35")
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
        with assume: assert size == 18
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 35', 0, iStep, False)
        # 第二次
        logging.info("second answer NRC35")
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
        with assume: assert size == 18
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 35', 0, iStep, False)
        # 第三次
        logging.info("third answer NRC36")
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
        with assume: assert size == 18
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 36', 0, iStep, False)
        time.sleep(2)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '3E 00', '7E 00', 0, iStep, False)
        logging.info("the first NRC37")
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '7F 27 37', 0, iStep, False)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 24', 0, iStep, False)
        time.sleep(2)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '3E 00', '7E 00', 0, iStep, False)
        logging.info("the two NRC37")
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '7F 27 37', 0, iStep, False)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 24', 0, iStep, False)
        time.sleep(2)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '3E 00', '7E 00', 0, iStep, False)
        logging.info("the three NRC37")
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '7F 27 37', 0, iStep, False)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 24', 0, iStep, False)
        time.sleep(3)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '3E 00', '7E 00', 0, iStep, False)
        logging.info("the four NRC37")
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '7F 27 37', 0, iStep, False)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 24', 0, iStep, False)
        time.sleep(3)
        logging.info("the sid 0x27 normal")
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '3E 00', '7E 00', 0, iStep, False)
        iStep = Driver['CAN'].unlock(Driver, iStep, 2)
          

    ids = [f"Request {req}" for req, _ in SecurityAccess_Seed_NRC13]
    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-安全访问请求种子NRC13错误码')
    @allure.description('测试物理寻址编程会话下请求种子的NRC13错误码')
    @pytest.mark.parametrize('req,resp',SecurityAccess_Seed_NRC13,ids=ids)
    def test_SecurityAccess_Seed_NRC13_Programming_Phy(self, action, Driver, req, resp):
        iStep = 1
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, 2, iStep, False)

    
    ids = [f"Request {req}" for req, _ in SecurityAccess_Seed_NRC12]
    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-安全访问请求种子NRC12错误码')
    @allure.description('测试物理寻址编程会话下请求种子的NRC12错误码')
    @pytest.mark.parametrize('req,resp',SecurityAccess_Seed_NRC12,ids=ids)
    def test_SecurityAccess_Seed_NRC12_Programming_Phy(self, action, Driver, req, resp):
        iStep = 1
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, 2, iStep, False)


    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-安全访问请求密钥正响应')
    @allure.description('测试物理寻址编程会话下请求密钥的正响应')
    def test_SecurityAccess_Key_Programming_Phy(self, action, Driver):
        iStep = 1
        # 安全解锁后再次请求种子应该返回全零的种子
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11 ' + '00' * 16, 2, iStep, True)
        with assume: assert size == 18  

    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-安全访问发送密钥NRC35 36 37错误码')
    @allure.description('测试物理寻址编程会话下发送密钥的NRC35 36 37错误码')
    def test_SecurityAccess_Key_NRC_Programming_Phy(self, action, Driver):
        iStep = 1
        reqKey = '27 12' +'11' * 16  # 共34字节(18个双字符)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 24', 2, iStep, False)
        # 安全解锁后再次请求种子应该返回全零的种子
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11 ' + '00' * 16, 2, iStep, True)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 24', 0, iStep, False)

        iStep = Driver['CAN'].restartETC_Power(Driver,iStep)
        # Test NRC35 of key of 0x27
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
        with assume: assert size == 18
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 35', 0, iStep, False)

        # Test NRC35 of key of 0x27
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
        with assume: assert size == 18
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 35', 0, iStep, False)

        # Test NRC36 of key of 0x27
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 0, iStep, False)
        with assume: assert size == 18
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 36', 0, iStep, False)

        for i in range(4):
            iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '7F 27 37', 0, iStep, False)
            iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 24', 0, iStep, False)
            time.sleep(2)
        time.sleep(1)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '3E 00', '7E 00', 0, iStep, False)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '7F 27 37', 0, iStep, False)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 24', 0, iStep, False)
        time.sleep(2.5)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '3E 00', '7E 00', 0, iStep, False)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
        with assume: assert size == 18
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 36', 0, iStep, False)
        for i in range(5):
            iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '3E 00', '7E 00', 0, iStep, False)
            time.sleep(2)
        time.sleep(1)
        iStep = Driver['CAN'].unlock(Driver, iStep, 2)


    ids = [f"Request {req}" for req, _ in SecurityAccess_Key_NRC13]
    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-安全访问发送密钥NRC13错误码')
    @allure.description('测试物理寻址编程会话下发送密钥的NRC13错误码')
    @pytest.mark.parametrize('req,resp',SecurityAccess_Key_NRC13,ids=ids)
    def test_SecurityAccess_Key_NRC13_Programming_Phy(self, action, Driver, req, resp):
        iStep = 1
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, 2, iStep, False)

    ids = [f"Request {req}" for req, _ in SecurityAccess_Key_NRC12]
    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-安全访问发送密钥NRC12错误码')
    @allure.description('测试物理寻址编程会话下发送密钥的NRC12错误码')
    @pytest.mark.parametrize('req,resp',SecurityAccess_Key_NRC12,ids=ids)
    def test_SecurityAccess_Key_NRC12_Programming_Phy(self, action, Driver, req, resp):
        iStep = 1
        # iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
        # with assume: assert size == 18
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, 2, iStep, False)



    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-安全访问请求,收到正响应，无访问延时')
    @allure.description('测试ECU上电后安全访问请求的正响应及无延时情况')
    def test_SecurityAccess_delay_after_power_on_Programming_Phy(self, action, Driver):
        """测试ECU上电后安全访问流程"""
        logging.info("Test delay response of 0x27 after ECU power on")
        
        # 初始化步骤和种子
        iStep = 1
        seed = []
        # 1. 请求种子并验证响应
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
        with assume: 
            assert size == 18
            seed = uds_resp[2:18]
            assert seed != [0x00]*16  # 验证种子非全零
            assert seed != [0xFF]*16  # 验证种子非全FF
        # 计算并发送正确密钥
        reqKey = [0x27, 0x12] + list(AESCMAC.calculate(seed, level2_key))
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '67 12', 0, iStep, False)


    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-复位后,安全访问请求,收到正响应，无访问延时')
    @allure.description('测试物理寻址编程会话下复位后,安全访问请求,收到正响应，无访问延时')
    def test_SecurityAccess_delay_after_reset_Programming_Phy(self, action, Driver):
        """测试ECU复位后安全访问流程"""
        logging.info("Test delay response of 0x27 after ECU reset---start")
        time.sleep(0.5)
        iStep = 1
        
        # 1. ECU复位
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, "11 01", "51 01", 2, iStep, True)
        time.sleep(3)  # 等待ECU完全启动
        # 2. 请求种子并验证响应
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
        with assume: 
            assert size == 18
            seed = uds_resp[2:18]
            assert seed != [0x00]*16  # 验证种子非全零
            assert seed != [0xFF]*16  # 验证种子非全FF
        # 计算并发送正确密钥
        reqKey = [0x27, 0x12] + list(AESCMAC.calculate(seed, level2_key))
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '67 12', 0, iStep, False)


    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-安全访问失败2次后,延时10s后安全访问收到正响应')
    @allure.description('测试物理寻址编程会话下安全访问失败2次后,延时10s后安全访问收到正响应')
    def test_SecurityAccess_delay_after_failure_twice_Programming_Phy(self, action, Driver):
        """测试安全访问失败2次后的延时响应"""
        logging.info("Test delay response of 0x27 after SecurityAccess fail twice---start")
        time.sleep(0.5)
        iStep = 1
        seed = []
        reqKey = '27 12' +'11' * 16  # 构造错误的密钥请求
        
        # 两次失败的请求循环
        for i in range(2):
            session = 2 if i == 0 else 0  # 第一次用会话3，后续用当前会话
            # 请求种子
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', session, iStep, False)
            with assume: assert size == 18
            # 发送错误密钥
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '7F 27 35', 0, iStep, False)
        # 延时10s后重试
        logging.info('wait 10s')
        time.sleep(10)
        # 成功请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
        with assume: 
            assert size == 18
            seed = uds_resp[2:18]
            assert seed != [0x00]*16  # 验证种子有效性
        
        # 计算并发送正确密钥
        reqKey = [0x27, 0x12] + list(AESCMAC.calculate(seed, level2_key))
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '67 12', 0, iStep, False)

     
    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-安全访问请求三次种子,三次应该都相同')
    @allure.description('测试物理寻址编程会话下安全访问请求三次种子,三次应该都相同')
    def test_SecurityAccess_Three_Seed_Programming_Phy(self, action, Driver):
        """测试三次种子请求的唯一性"""
        iStep = 1
        seeds = []
        
        # 获取三个种子并验证长度是否正确
        for i in range(3):
            time.sleep(0.2)
            session = 2 if i == 0 else 0  # 第一次用会话3，后续用当前会话
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', session, iStep, False)
            with assume:
                assert size == 18
                seed = uds_resp[2:18]
                seeds.append(seed)
        
        # 验证种子唯一性和有效性
        with assume:
            assert len(set(tuple(seed) for seed in seeds)) == 1  # 确保三个种子都相同
            assert all(seed != [0x00]*16 for seed in seeds)     # 确保种子不是全零
            assert all(seed != [0xFF]*16 for seed in seeds)     # 确保种子不是全FF
        # 计算并发送密钥
        reqKey = [0x27, 0x12] + list(AESCMAC.calculate(seed, level2_key))
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, reqKey, '67 12', 0, iStep, False)

     
    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-安全访问请求5次种子，第4次应该响应NRC36,第5次响应NRC37')
    @allure.description('测试物理寻址编程会话下安全访问请求5次种子，第4次应该响应NRC36,第5次响应NRC37')
    def test_SecurityAccess_Five_Seed_NRC36_NRC37_Programming_Phy(self, action, Driver):
        iStep = 1
        time.sleep(0.1)
        # 获取并验证三个种子
        seeds = []
        for i in range(3):
            session = 2 if i == 0 else 0  # 第一次用会话2，后续用当前会话
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', session, iStep, False)
            with assume:
                assert size == 18
                seed = uds_resp[2:18]
                assert seed != [0x00]*16 and seed != [0xFF]*16  # 验证种子有效性
                seeds.append(seed)
            
            if i < 2:  # 前两次请求后等待
                time.sleep(0.2)

        # 第4次请求并验证NRC36响应
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '7F 27 36', 0, iStep, False)
        # 第5次请求并验证NRC37响应
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '7F 27 37', 0, iStep, False)
        # 等待10秒后解锁
        for i in range(5):
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '3E 00', '7E 00', 0, iStep, False)
            time.sleep(2)
        time.sleep(0.5)
        iStep = Driver['CAN'].unlock(Driver, iStep, 2)
        

     
    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-安全解锁后请求种子,应返回全零的种子，切换会话后再次请求种子,应返回非全零的种子')
    @allure.description('测试物理寻址编程会话下安全解锁后请求种子,应返回全零的种子，切换会话后再次请求种子,应返回非全零的种子')
    def test_SecurityAccess_changeSession_Programming_Phy(self, action, Driver):
        iStep = 1
        time.sleep(0.1)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, True)
        with assume: 
            assert size == 18
            assert uds_resp[2:18] == [0x00]*16
        time.sleep(0.1)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '10 01', '50 01', 0, iStep, False)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '10 03', '50 03', 0, iStep, False)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '10 02', '50 02', 0, iStep, False)
        time.sleep(0.1)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 0, iStep, False)
        with assume: 
            assert size == 18
            assert uds_resp[2:18] != [0x00] * 16
        iStep = Driver['CAN'].unlock(Driver, iStep, 2)

     
    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-安全访问请求种子,不重复的种子数应大于95%')
    @allure.description('测试200次安全访问请求种子的唯一性，要求不重复率>95%')
    def test_SecurityAccess_Seed_kpi_Programming_Phy(self, action, Driver):
        """安全访问种子唯一性KPI测试"""
        TEST_COUNT = 200    # 测试次数
        LOG_INTERVAL = 50   # 日志输出间隔
        seed_history = []   # 记录已出现的种子
        duplicate_count = 0 # 记录重复次数
        
        # 初始化测试环境
        iStep = 1
        iStep, _, _ = Driver['CAN'].checkReqResp(Driver, '3E 00', '7E 00', 2, iStep, False)
        
        for i in range(TEST_COUNT):
            time.sleep(0.1)
            # 请求种子
            iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, '27 11', '67 11', 2, iStep, False)
            # 验证种子有效性
            with assume: 
                assert size == 18
                seed = uds_resp[2:18]
                assert seed != [0x00]*16 and seed != [0xFF]*16
                
            # 统计唯一性
            if seed in seed_history:
                duplicate_count += 1
            else:
                seed_history.append(seed)
            
            # 定期重启ECU
            if i % 5 == 0 and i % 10 != 0:
                iStep = Driver['CAN'].restartETC_Power(Driver, iStep)
            elif i % 10 == 0:
                iStep = Driver['CAN'].restartETC_11(Driver, iStep)
            # 切换到编程会话
            iStep, _, _ = Driver['CAN'].checkReqResp(Driver, '3E 00', '7E 00', 2, iStep, False)
            
            # 定期输出日志
            if i % LOG_INTERVAL == 0:
                uniqueness = len(seed_history)/(i+1)*100
                logging.info(
                    f"进度: {i+1}/{TEST_COUNT}, "
                    f"唯一种子: {len(seed_history)}, "
                    f"唯一性: {uniqueness:.2f}%"
                )
        # 最终结果验证
        uniqueness_ratio = len(seed_history)/TEST_COUNT
        logging.info(
            f"测试完成 - 总请求: {TEST_COUNT}, "
            f"唯一种子: {len(seed_history)}, "
            f"重复次数: {duplicate_count}, "
            f"唯一性比例: {uniqueness_ratio*100:.2f}%"
        )
        with assume: 
            assert uniqueness_ratio > 0.95
            assert duplicate_count < 10


class Test_BOOT_SecurityAccess_Func(object):
    ids = [f"Request {req}" for req, _ in SecurityAccess_Noresponse]
    @allure.severity('normal')
    @allure.title('功能寻址,编程会话下安全访问请求应无响应')
    @allure.description('测试功能寻址,编程会话下下安全访问请求应无响应')
    @pytest.mark.parametrize('req,resp',SecurityAccess_Noresponse,ids=ids)
    def test_SecurityAccess_NoResponse_Default_Func(self, action, Driver, req, resp):
        """验证27服务在功能寻址下应无响应"""
        iStep = 1
        # 功能寻址请求
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, 2, iStep, False, 'UDSFun')
        with assume: 
            assert size == 0  # 验证无响应
            assert uds_resp == []  # 验证响应为空